package com.xhy.documents_collection.aop;

import com.xhy.documents_collection.annotations.OperLog;
import com.xhy.documents_collection.entity.PO.log.SysLog;
import com.xhy.documents_collection.enums.BusinessType;
import com.xhy.documents_collection.enums.ServiceType;
import com.xhy.documents_collection.holder.UserHolder;
import com.xhy.documents_collection.restrict.RestrictHandler;
import com.xhy.documents_collection.service.sys.SysLogService;
import com.xhy.documents_collection.thread_pool.LogThreadPool;
import com.xhy.documents_collection.utils.IpUtils;
import com.xhy.documents_collection.utils.JwtUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.NamedThreadLocal;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * Author: Xhy
 * CreateTime: 2023-03-08 09:40
 */
@Aspect
@Component
public class OperLogAop {

    @Autowired
    HttpServletRequest request;

    @Autowired
    RestrictHandler restrictHandler;

    private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");

    @Before("@annotation(operLog)")
    public void before(JoinPoint joinPoint, OperLog operLog) throws Throwable {
        String userId = JwtUtils.getMemberIdByJwtToken(request);
        UserHolder.set(userId);
        TIME_THREADLOCAL.set(System.currentTimeMillis());
    }

    @AfterReturning("@annotation(operLog)")
    public void after(JoinPoint joinPoint, OperLog operLog)
    {
        handleLog(operLog,null);
    }

    @AfterThrowing(value = "@annotation(operLog)", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint,  OperLog operLog, Exception e)
    {
        handleLog(operLog,e);
    }

    private void handleLog(OperLog operLog, Exception e) {

        String title = operLog.title().getName();
        BusinessType businessType = operLog.businessType();
        Integer userId = UserHolder.get();
        String ipAddr = IpUtils.getIpAddr(request);
        SysLog sysLog = new SysLog();
        sysLog.setTitle(title);
        sysLog.setBusinessType(businessType.ordinal());
        sysLog.setUId(userId);
        sysLog.setIp(ipAddr);
        sysLog.setState(true);
        sysLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get());
        if (e!=null){
            sysLog.setState(false);
        }
        try {
            LogThreadPool.addOperLog(sysLog);
        }catch (Exception exp){
           exp.printStackTrace();
        }finally {
            UserHolder.clear();
        }
    }
}
